package com.zxw.factory;

import com.lmax.disruptor.EventFactory;
import com.lmax.disruptor.SleepingWaitStrategy;
import com.lmax.disruptor.dsl.Disruptor;
import com.lmax.disruptor.dsl.ProducerType;
import com.zxw.consumer.AbsDisruptorConsumer;
import com.zxw.entity.ObjectEvent;
import com.zxw.queue.DisruptorQueue;
import lombok.NoArgsConstructor;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;

/**
 * @author by zhuxiansheng
 * @description 队列操作工具类工厂
 * @date
 */
@NoArgsConstructor
public class DisruptorQueueFactory {

    /**
     * 等待策略
     *   Disruptor 提供了多个 WaitStrategy（等待策略）的实现，每种策略都具有不同性能和优缺点，根据实际运行环境的 CPU 的硬件特点选择恰当的策略，并配合特定的 JVM 的配置参数，能够实现不同的性能提升：
     *   BlockingWaitStrategy 是最低效的策略，但其对 CPU 的消耗最小并且在各种不同部署环境中能提供更加一致的性能表现；
     *   SleepingWaitStrategy 的性能表现跟 BlockingWaitStrategy 差不多，对 CPU 的消耗也类似，但其对生产者线程的影响最小，适合用于异步日志类似的场景；
     *   YieldingWaitStrategy 的性能是最好的，适合用于低延迟的系统。在要求极高性能且事件处理线数小于 CPU 逻辑核心数的场景中，推荐使用此策略；例如：CPU 开启超线程的特性。
     */


    /**
     * 创建一个点对点模式的操作队列，即一个事件会被一组消费者中的其中一个消费
     * @param queueSize 队列大小
     * @param isMoreProducer 是否是多生产者
     * @param consumers 消费者
     * @param <T>
     * @return
     */
    public static <T> DisruptorQueue<T> getWorkPoolQueue(int queueSize, boolean isMoreProducer, AbsDisruptorConsumer<T>... consumers) {

        Disruptor<ObjectEvent<T>> disruptor = new Disruptor<ObjectEvent<T>>(new ObjectEventFactory<>(),
                queueSize, Executors.defaultThreadFactory(),
                isMoreProducer ? ProducerType.MULTI : ProducerType.SINGLE,
                new SleepingWaitStrategy());
        disruptor.handleEventsWithWorkerPool(consumers);
        return new DisruptorQueue<>(disruptor);
    }

    /**
     * 创建一个发布/订阅模式的操作队列，即一个事件会被多个消费者消费
     * @param queueSize
     * @param isMoreProducer
     * @param consumers
     * @param <T>
     * @return
     */
    public static <T> DisruptorQueue<T> getHandleEventsQueue(int queueSize, boolean isMoreProducer,
                                                             AbsDisruptorConsumer<T>... consumers) {
        Disruptor<ObjectEvent<T>> disruptor = new Disruptor(new ObjectEventFactory(),
                queueSize, Executors.defaultThreadFactory(),
                isMoreProducer ? ProducerType.MULTI : ProducerType.SINGLE,
                new SleepingWaitStrategy());
        disruptor.handleEventsWith(consumers);
        return new DisruptorQueue(disruptor);
    }

    /**
     * 直接通过传入的 Disruptor 对象创建操作队列（如果消费者有依赖关系的话可以用此方法）
     * @param disruptor
     * @param <T>
     * @return
     */
    public static <T> DisruptorQueue<T> getQueue(Disruptor<ObjectEvent<T>> disruptor) {
        return new DisruptorQueue(disruptor);
    }

}
